// Η κλάση "Anazitisi" αφορά στην αναζήτηση παικτών στα πλαίσια ενός σκηνικού.
// Ως properties περιέχονται τόσο τα κριτήρια αναζήτησης όσο και τα αποτελέσματα:
//
//	onoma		Περιέχει το pattern αναζήτησης που καθορίζει ο χρήστης στο
//			σχετικό input πεδίο και το οποίο εμπλουτίζεται με ειδικούς
//			μεταχαρακτήρες.
//
//	sxesi		Καθορίζει το αν η αναζήτηση αφορά μόνο σε συσχετισμένους
//			παίκτες (1) ή σε όλους τους παίκτες (0).
//
//	katastasi	Καθορίζει την κατάσταση των αναζητουμένων παικτών, ήτοι:
//
//			0	Παίκτες αναξαρτήτως κατάστασης.
//
//			1	Online παίκτες.
//
//			2	Online διαθέσιμοι παίκτες.
//
//	epilogi		Λίστα αποτελεσμάτων αναζήτησης δεικτοδοτημένη με το login
//			name του παίκτη.
//
// Υπάρχουν και δομικά properties που δεν αφορούν την ίδια την αναζήτηση αλλά τον
// τρόπο που αυτή λειτουργεί και εντάσσεται στη γενικότερη αρχιτεκτονική:
//
//	skiniko		Είναι το σκηνικό στο οποίο εντάσσεται ως property η ίδια
//			η αναζήτησης και στα πλαίσια του οποίου εκτελείται.
//
//	timer		Πρόκειται για δρομολογημένη εκτέλεση της αναζήτησης, δηλαδή
//			για αναζήτηση που θα εκτελεστεί οσονούπω. Χρησιμοποιείται
//			κυρίως κατά την πληκτρολόγηση του ονόματος, όπου με κάθε
//			πληκτρισμό δρομολογείται νέα αναζήτηση δίνοντας λίγο χρόνο
//			για τον επόμενο πληκτρισμό.

Anazitisi = function(props) {
	var skiniko;

	this.onoma = '';
	this.sxesi = 0;
	this.katastasi = 0;
	this.epilogi = {};

	globals.initObject(this, props, {recursive: false});
}

Anazitisi.prototype.skinikoGet = function() {
	return this.skiniko;
}

Anazitisi.prototype.timerSet = function(timer) {
	this.timer = timer;
	return this;
}

Anazitisi.prototype.timerGet = function() {
	return this.timer;
}

Anazitisi.prototype.timerClear = function() {
	var timer = this.timerGet();
	if (timer) clearTimeout(timer);
	delete this.timer;
	return this;
}

Anazitisi.prototype.onomaSet = function(onoma) {
	this.onoma = onoma;
	return this;
}

Anazitisi.prototype.onomaGet = function() {
	return this.onoma;
}

Anazitisi.prototype.sxesiSet = function(sxesi, dom) {
	this.sxesi = sxesi;
	if (!dom) return this;

	switch (sxesi) {
	case 1:
		this.sxesiDOM.attr({
			src: 'ikona/pss/sxesiNai.png',
			title: 'Συσχετισμένοι',
		});
		break;
	default:
		this.sxesiDOM.attr({
			src: 'ikona/pss/sxesiOxi.png',
			title: 'Όλοι οι παίκτες',
		});
		break;
	}

	return this;
}

Anazitisi.prototype.sxesiGet = function() {
	return this.sxesi;
}

Anazitisi.prototype.katastasiSet = function(katastasi, dom) {
	this.katastasi = katastasi;
	if (!dom) return this;

	switch (katastasi) {
	case 2:
		dom.attr({
			src: 'ikona/pss/katastasiAvailable.png',
			title: 'Online, διαθέσιμοι',
		});
		break;
	case 1:
		dom.attr({
			src: 'ikona/pss/katastasiOnline.png',
			title: 'Online παίκτες',
		});
		break;
	default:
		dom.attr({
			src: 'ikona/pss/katastasiAll.png',
			title: 'Ανεξαρτήτως κατάστασης',
		});
		break;
	}

	return this;
}

Anazitisi.prototype.katastasiGet = function() {
	return this.katastasi;
}

Anazitisi.prototype.epilogiGet = function(login) {
	return this.epilogi[login];
}

Anazitisi.prototype.epilogiClear = function() {
	this.epilogi = {};
	return this;
}

Anazitisi.prototype.epilogiAdd = function(epilogi) {
	this.epilogi[epilogi.loginGet()] = epilogi;
	return this;
}

Anazitisi.prototype.epilogiDelete = function(login) {
	delete this.epilogi[login];
	return this;
}

Anazitisi.prototype.epilogiWalk = function(callback) {
	globals.walk(this.epilogi, callback);
	return this;
}

Anazitisi.prototype.anazitisiAskopi = function() {
	if (this.onomaGet()) return false;
	if (this.sxesiGet()) return false;
	if (this.katastasiGet()) return false;
	return true;
}

Anazitisi.prototype.anazitisiClearDOM = function(dom) {
	dom.empty();
	return this;
}

Anazitisi.prototype.anazitisi = function() {
	var anazitisi = this, skiniko = this.skinikoGet(), dom, pektis, onoma, sxesi, katastasi;

	this.timerClear();
	this.epilogiClear();

	dom = skiniko.sxesiGetDOM();
	if (!dom) return this;
	if (!dom.length) return this;

	pektis = skiniko.pektisEgo();
	if (!pektis) return this.anazitisiClearDOM(dom);

	sxesi = this.sxesiGet();
	katastasi = this.katastasiGet();
	if (sxesi) return this.anazitisiLocal(skiniko, pektis, sxesi, katastasi, dom);
	if (katastasi) return this.anazitisiLocal(skiniko, pektis, sxesi, katastasi, dom);

	onoma = this.onomaGet();
	if (!onoma) return this.anazitisiClearDOM(dom);

	this.anazitisiSkiser(skiniko, pektis, onoma, dom);
	return this;
}

Anazitisi.prototype.anazitisiLocal = function(skiniko, pektis, sxesi, katastasi, dom) {
	var anazitisi = this, onoma = this.onomaGet();

	// By default ισχύουν οι μεταχαρακτήρες της SQL, επειδή όμως εδώ θα γίνει έλεγχος
	// με την match της Javascript, τους αλλάζουμε σε μεταχαρακτήρες RE.

	if (onoma) onoma = onoma.replace(/%/g, '.*').replace(/_/g, '.');
	dom.empty();

	if (sxesi) {
		pektis = skiniko.pektisEgoFetch();
		pektis.sxesiWalk(function(login, sxesi) {
			if (onoma && (!login.match(onoma))) return;
			if (katastasi && skiniko.oxiSinedria(login)) return;
			anazitisi.epilogiAdd(new Epilogi({
				login: login,
			}));
		});
	}
	else if (katastasi) {
		skiniko.sinedriaWalk(function(login, sinedria) {
			if (onoma && (!login.match(onoma))) return;
			if ((katastasi == 2) && (sinedria.simetoxiGet() == 'ΠΑΙΚΤΗΣ')) return;
			anazitisi.epilogiAdd(new Epilogi({
				login: login,
			}));
		});
	}
	else return this;

	anazitisi.epilogiWalk(function(login, epilogi) {
		dom.append(epilogi.epilogiGetDOM(skiniko));
	});

	return this;
}

Anazitisi.prototype.anazitisiSkiser = function(skiniko, pektis, onoma, dom) {
	var anazitisi = this, working;

	working = anazitisi.resetDOM.attr({src:'ikona/working/default.gif'});
	client.node('pektisAnazitisi', 'onoma=' + onoma.uri(), function(xhr) {
		var res, i;

		working.attr({src:'ikona/pss/clear.png'});
		dom.empty();
		if (xhr.sfalma) return;
		if (!xhr.responseText) return;

		try {
			eval('res = [' + xhr.responseText + '];');
		}
		catch (e) {
			return client.fyi.epano('Λανθασμένα αποτελέσματα αναζήτησης');
		}

		res.sort(function(e1, e2) {
			var sxesi1, sxesi2;

			sxesi1 = pektis.sxesiGet(e1.l);
			if (sxesi1) sxesi1 = sxesi1.sxesiGet();

			sxesi2 = pektis.sxesiGet(e2.l);
			if (sxesi2) sxesi2 = sxesi2.sxesiGet();

			if (sxesi1 == 'ΦΙΛΟΣ') {
				if (sxesi2 != 'ΦΙΛΟΣ') return -1;
			}
			else if (sxesi2 == 'ΦΙΛΟΣ') return 1;
			else if (sxesi1 == 'ΑΠΟΚΛΕΙΣΜΕΝΟΣ') {
				if (sxesi2 != 'ΑΠΟΚΛΕΙΣΜΕΝΟΣ') return 1;
			}
			else if (sxesi2 == 'ΑΠΟΚΛΕΙΣΜΕΝΟΣ') return -1;

			return e1.l.localeCompare(e2.l);
		});

		for (i = 0; i < res.length; i++) {
			anazitisi.epilogiAdd(new Epilogi({
				login: res[i].l,
				onoma: res[i].o,
			}));
		}

		anazitisi.epilogiWalk(function(login, epilogi) {
			dom.append(epilogi.epilogiGetDOM(skiniko));
		});
	});

	return this;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////@

// Τα αποτελέσματα μια αναζήτησης παρίστανται από αντικείμενα κλάσης "Epilogi" τα οποία
// εντάσσονται σε λίστα της αναζήτησης. Τα αντικείμενα αυτά περιέχουν το login name του
// παίκτη και το όνομα του παίκτη, εφόσον ο παίκτης δεν υπάρχει στο σκηνικό.

Epilogi = function(props) {
	globals.initObject(this, props);
}

Epilogi.prototype.loginGet = function() {
	return this.login;
}

Epilogi.prototype.onomaGet = function(skiniko) {
	var pektis;
	if (this.hasOwnProperty('onoma')) return this.onoma;
	if (!skiniko) return '';
	pektis = skiniko.pektisGet(this.loginGet());
	if (pektis) return pektis.onomaGet();
	return '';
}

Epilogi.prototype.katastasiGet = function() {
	return this.katastasi;
}

Epilogi.prototype.epilogiGetDOM = function(skiniko) {
	var kat;

	if (this.hasOwnProperty('DOM')) return this.DOM;

	this.DOM = $('<div>').addClass('anazitisi');
	this.epilogiRefreshDOM(skiniko);
	return this.DOM;
}

Epilogi.prototype.epilogiRefreshDOM = function(skiniko) {
	var login, sinedria, katastasi;

	login = this.loginGet();
	sinedria = skiniko.sinedriaGet(login);
	if (sinedria) katastasi = sinedria.simetoxiGet() != 'ΠΑΙΚΤΗΣ' ? 'Available' : 'Online';
	else katastasi = 'All';

	this.epilogiGetDOM(skiniko).empty().
	append($('<img>').addClass('pssIcon anazitisiKatastasiIcon').attr({
		src: 'ikona/pss/katastasi' + katastasi + '.png',
	})).
	append($('<div>').addClass('anazitisiLogin').text(login).pektisOplismos(skiniko, login)).
	append(this.onomaGet(skiniko));

	return this;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////@

Skiniko.prototype.anazitisiGet = function() {
	if (this.hasOwnProperty('anazitisi')) return this.anazitisi;

	this.anazitisi = new Anazitisi({
		skiniko: this,
	});
	return this.anazitisi.anazitisi();
}

Skiniko.prototype.anazitisiInputCreateDOM = function() {
	var skiniko = this, anazitisi = this.anazitisiGet();

	anazitisi.inputDOM = $('<input>').addClass('pssHeaderInput').attr({
		size: 20,
		title: 'Αναζήτηση παικτών',
	}).
	on('click', function(e) {
		e.stopPropagation();
		skiniko.trexonInputSet($(this));
		$(this).focus();
	}).
	on('keyup', function(e) {
		var timer, len;

		e.stopPropagation();
		timer = anazitisi.timerGet();
		if (timer) clearTimeout(timer);

		if (e.which == 27) {
			$(this).val('');
			delay = 100;
		}
		else {
			len = $(this).val().length;
			if (len < 2) delay = 800;
			else if (len == 2) delay = 700;
			else if (len == 3) delay = 500;
			else delay = 300;
		}

		anazitisi.onomaSet($(this).val());
		anazitisi.timerSet(setTimeout(function() {
			anazitisi.anazitisi();
		}, delay));
	});

	skiniko.trexonInputSet(anazitisi.inputDOM);
	return anazitisi.inputDOM;
}

Skiniko.prototype.anazitisiResetCreateDOM = function() {
	var skiniko = this, anazitisi = this.anazitisiGet(), dom;

	anazitisi.resetDOM = $('<img>').addClass('pssHeaderIcon').attr({
		src: 'ikona/pss/clear.png',
		title: 'Καθαρισμός κριτηρίων αναζήτησης',
	}).
	on('click', function(e) {
		e.stopPropagation();
		anazitisi.inputDOM.val('');
		anazitisi.
		onomaSet('').
		sxesiSet(0, true).
		katastasiSet(0, $('#anazitisiKatastasiIcon')).
		anazitisi();
	});

	return anazitisi.resetDOM;
}

Skiniko.prototype.anazitisiSxesiCreateDOM = function() {
	var skiniko = this, anazitisi = this.anazitisiGet();

	anazitisi.sxesiDOM = $('<img>').addClass('pssHeaderIcon').
	on('click', function(e) {
		e.stopPropagation();
		switch (anazitisi.sxesiGet()) {
		case 0:
			anazitisi.sxesiSet(1, true);
			break;
		default:
			anazitisi.sxesiSet(0, true);
			break;
		}

		anazitisi.anazitisi();
	});

	anazitisi.sxesiSet(anazitisi.sxesiGet(), true);
	return anazitisi.sxesiDOM;
}

Skiniko.prototype.anazitisiKatastasiCreateDOM = function() {
	var skiniko = this, anazitisi = this.anazitisiGet(), dom;

	dom = $('<img>').addClass('pssHeaderIcon').attr({
		id: 'anazitisiKatastasiIcon',
		src: 'ikona/pss/katastasiAll.png',
		title: 'Ανεξαρτήτως κατάστασης',
	}).
	on('click', function(e) {
		e.stopPropagation();
		switch (anazitisi.katastasiGet()) {
		case 1:
			anazitisi.katastasiSet(2, dom);
			break;
		case 2:
			anazitisi.katastasiSet(0, dom);
			break;
		default:
			anazitisi.katastasiSet(1, dom);
			break;
		}

		anazitisi.anazitisi();
	});

	anazitisi.katastasiSet(anazitisi.katastasiGet(), dom);
	return dom;
}

Skiniko.prototype.epilogiRefreshDOM = function(login) {
	var anazitisi = this.anazitisiGet(), epilogi, simfoni;

	epilogi = anazitisi.epilogiGet(login);
	simfoni = anazitisi.pektisSimfoni(login);

	if (simfoni) {
		if (epilogi) {
			epilogi.epilogiRefreshDOM(this);
			return this;
		}

		if (anazitisi.anazitisiAskopi()) return this;

		epilogi = new Epilogi({
			login: login,
		});
		epilogi.epilogiGetDOM(this).prependTo(this.sxesiGetDOM());
		anazitisi.epilogiAdd(epilogi);
		if (anazitisi.pektisEndiaferon(login)) client.ixos.ding();
		return this;
	}
	
	if (!epilogi) return this;

	epilogi.epilogiGetDOM(this).remove();
	anazitisi.epilogiDelete(login);
	return this;
}

Skiniko.prototype.anazitisiArxiki = function() {
	var anazitisi = this.anazitisiGet(), sxesi;
	if (!anazitisi) return this;
	sxesi = anazitisi.sxesiDOM;
	if (!sxesi) return this;
	sxesi.trigger('click');
	return this;
}

Anazitisi.prototype.pektisSimfoni = function(login) {
	var skiniko = this.skinikoGet(), onoma, sinedria, simetoxi, katastasi, sxesi, ego;

	onoma = this.onomaGet();
	if (onoma && (!login.match(onoma))) return false;

	sinedria = skiniko.sinedriaGet(login);

	katastasi = this.katastasiGet();
	if (katastasi) {
		if (!sinedria) return false;
		simetoxi = sinedria.simetoxiGet();
		if ((katastasi == 2) && (simetoxi == 'ΠΑΙΚΤΗΣ')) return false;
	}

	sxesi = this.sxesiGet();
	if (sxesi) {
		ego = skiniko.pektisEgoFetch();
		if (!ego.sxesiGet(login)) return false;
	}

	return true;
}

Anazitisi.prototype.pektisEndiaferon = function(login) {
	var skiniko = this.skinikoGet();

	if (this.onomaGet()) return true;
	if (this.skinikoGet().pektisEgoFetch().sxesiGet(login)) return true;
	return false;
}
